/*
* Copyright (C) 2014 MediaTek Inc.
* Modification based on code covered by the mentioned copyright
* and/or permission notice(s).
*/
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony.cdma.sms;

import android.content.res.Resources;
import android.telephony.SmsCbCmasInfo;
import android.telephony.cdma.CdmaSmsCbProgramData;
import android.telephony.cdma.CdmaSmsCbProgramResults;
import android.text.format.Time;
import android.telephony.Rlog;

import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;

import java.util.ArrayList;
import java.util.TimeZone;

import com.htc.internal.telephony.HtcSmsUtils;

/**
 * An object to encode and decode CDMA SMS bearer data.
 */
public final class BearerData {
    private final static String LOG_TAG = "BearerData";

    /**
     * Bearer Data Subparameter Identifiers
     * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
     * NOTE: Commented subparameter types are not implemented.
     */
    private final static byte SUBPARAM_MESSAGE_IDENTIFIER               = 0x00;
    private final static byte SUBPARAM_USER_DATA                        = 0x01;
    private final static byte SUBPARAM_USER_RESPONSE_CODE               = 0x02;
    private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP        = 0x03;
    private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE         = 0x04;
    private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE         = 0x05;
    private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE  = 0x06;
    private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE  = 0x07;
    private final static byte SUBPARAM_PRIORITY_INDICATOR               = 0x08;
    private final static byte SUBPARAM_PRIVACY_INDICATOR                = 0x09;
    private final static byte SUBPARAM_REPLY_OPTION                     = 0x0A;
    private final static byte SUBPARAM_NUMBER_OF_MESSAGES               = 0x0B;
    private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY        = 0x0C;
    private final static byte SUBPARAM_LANGUAGE_INDICATOR               = 0x0D;
    private final static byte SUBPARAM_CALLBACK_NUMBER                  = 0x0E;
    private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE             = 0x0F;
    //private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA      = 0x10;
    private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX            = 0x11;
    private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA    = 0x12;
    private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13;
    private final static byte SUBPARAM_MESSAGE_STATUS                   = 0x14;
    //private final static byte SUBPARAM_TP_FAILURE_CAUSE                 = 0x15;
    //private final static byte SUBPARAM_ENHANCED_VMN                     = 0x16;
    //private final static byte SUBPARAM_ENHANCED_VMN_ACK                 = 0x17;

    // All other values after this are reserved.
    private final static byte SUBPARAM_ID_LAST_DEFINED                    = 0x17;

    /**
     * Supported message types for CDMA SMS messages
     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
     */
    public static final int MESSAGE_TYPE_DELIVER        = 0x01;
    public static final int MESSAGE_TYPE_SUBMIT         = 0x02;
    public static final int MESSAGE_TYPE_CANCELLATION   = 0x03;
    public static final int MESSAGE_TYPE_DELIVERY_ACK   = 0x04;
    public static final int MESSAGE_TYPE_USER_ACK       = 0x05;
    public static final int MESSAGE_TYPE_READ_ACK       = 0x06;
    public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
    public static final int MESSAGE_TYPE_SUBMIT_REPORT  = 0x08;

    public int messageType;

    /**
     * 16-bit value indicating the message ID, which increments modulo 65536.
     * (Special rules apply for WAP-messages.)
     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
     */
    public int messageId;

    /**
     * Supported priority modes for CDMA SMS messages
     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1)
     */
    public static final int PRIORITY_NORMAL        = 0x0;
    public static final int PRIORITY_INTERACTIVE   = 0x1;
    public static final int PRIORITY_URGENT        = 0x2;
    public static final int PRIORITY_EMERGENCY     = 0x3;

    public boolean priorityIndicatorSet = false;
    public int priority = PRIORITY_NORMAL;

    /**
     * Supported privacy modes for CDMA SMS messages
     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1)
     */
    public static final int PRIVACY_NOT_RESTRICTED = 0x0;
    public static final int PRIVACY_RESTRICTED     = 0x1;
    public static final int PRIVACY_CONFIDENTIAL   = 0x2;
    public static final int PRIVACY_SECRET         = 0x3;

    public boolean privacyIndicatorSet = false;
    public int privacy = PRIVACY_NOT_RESTRICTED;

    /**
     * Supported alert priority modes for CDMA SMS messages
     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1)
     */
    public static final int ALERT_DEFAULT          = 0x0;
    public static final int ALERT_LOW_PRIO         = 0x1;
    public static final int ALERT_MEDIUM_PRIO      = 0x2;
    public static final int ALERT_HIGH_PRIO        = 0x3;

    public boolean alertIndicatorSet = false;
    public int alert = ALERT_DEFAULT;

    /**
     * Supported display modes for CDMA SMS messages.  Display mode is
     * a 2-bit value used to indicate to the mobile station when to
     * display the received message.  (See 3GPP2 C.S0015-B, v2,
     * 4.5.16)
     */
    public static final int DISPLAY_MODE_IMMEDIATE      = 0x0;
    public static final int DISPLAY_MODE_DEFAULT        = 0x1;
    public static final int DISPLAY_MODE_USER           = 0x2;

    public boolean displayModeSet = false;
    public int displayMode = DISPLAY_MODE_DEFAULT;

    /**
     * Language Indicator values.  NOTE: the spec (3GPP2 C.S0015-B,
     * v2, 4.5.14) is ambiguous as to the meaning of this field, as it
     * refers to C.R1001-D but that reference has been crossed out.
     * It would seem reasonable to assume the values from C.R1001-F
     * (table 9.2-1) are to be used instead.
     */
    public static final int LANGUAGE_UNKNOWN  = 0x00;
    public static final int LANGUAGE_ENGLISH  = 0x01;
    public static final int LANGUAGE_FRENCH   = 0x02;
    public static final int LANGUAGE_SPANISH  = 0x03;
    public static final int LANGUAGE_JAPANESE = 0x04;
    public static final int LANGUAGE_KOREAN   = 0x05;
    public static final int LANGUAGE_CHINESE  = 0x06;
    public static final int LANGUAGE_HEBREW   = 0x07;

    public boolean languageIndicatorSet = false;
    public int language = LANGUAGE_UNKNOWN;

    /**
     * SMS Message Status Codes.  The first component of the Message
     * status indicates if an error has occurred and whether the error
     * is considered permanent or temporary.  The second component of
     * the Message status indicates the cause of the error (if any).
     * (See 3GPP2 C.S0015-B, v2.0, 4.5.21)
     */
    /* no-error codes */
    public static final int ERROR_NONE                   = 0x00;
    public static final int STATUS_ACCEPTED              = 0x00;
    public static final int STATUS_DEPOSITED_TO_INTERNET = 0x01;
    public static final int STATUS_DELIVERED             = 0x02;
    public static final int STATUS_CANCELLED             = 0x03;
    /* temporary-error and permanent-error codes */
    public static final int ERROR_TEMPORARY              = 0x02;
    public static final int STATUS_NETWORK_CONGESTION    = 0x04;
    public static final int STATUS_NETWORK_ERROR         = 0x05;
    public static final int STATUS_UNKNOWN_ERROR         = 0x1F;
    /* permanent-error codes */
    public static final int ERROR_PERMANENT              = 0x03;
    public static final int STATUS_CANCEL_FAILED         = 0x06;
    public static final int STATUS_BLOCKED_DESTINATION   = 0x07;
    public static final int STATUS_TEXT_TOO_LONG         = 0x08;
    public static final int STATUS_DUPLICATE_MESSAGE     = 0x09;
    public static final int STATUS_INVALID_DESTINATION   = 0x0A;
    public static final int STATUS_MESSAGE_EXPIRED       = 0x0D;
    /* undefined-status codes */
    public static final int ERROR_UNDEFINED              = 0xFF;
    public static final int STATUS_UNDEFINED             = 0xFF;

    public boolean messageStatusSet = false;
    public int errorClass = ERROR_UNDEFINED;
    public int messageStatus = STATUS_UNDEFINED;

    /**
     * 1-bit value that indicates whether a User Data Header (UDH) is present.
     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
     *
     * NOTE: during encoding, this value will be set based on the
     * presence of a UDH in the structured data, any existing setting
     * will be overwritten.
     */
    public boolean hasUserDataHeader;

    /**
     * provides the information for the user data
     * (e.g. padding bits, user data, user data header, etc)
     * (See 3GPP2 C.S.0015-B, v2, 4.5.2)
     */
    public UserData userData;

    /**
     * The User Response Code subparameter is used in the SMS User
     * Acknowledgment Message to respond to previously received short
     * messages. This message center-specific element carries the
     * identifier of a predefined response. (See 3GPP2 C.S.0015-B, v2,
     * 4.5.3)
     */
    public boolean userResponseCodeSet = false;
    public int userResponseCode;

    /**
     * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4
     */
    public static class TimeStamp extends Time {

        public TimeStamp() ;


        public static TimeStamp fromByteArray(byte[] data) ;


        // MTK_START: use to convert the local time to utc for sc time.
        public TimeStamp(String timeZone) ;


        public static TimeStamp fromByteArray(byte[] data, String timeZone) ;

        // MTK_END

        @Override
        public String toString() ;

    }

    public TimeStamp msgCenterTimeStamp;
    public TimeStamp validityPeriodAbsolute;
    public TimeStamp deferredDeliveryTimeAbsolute;

    /**
     * Relative time is specified as one byte, the value of which
     * falls into a series of ranges, as specified below.  The idea is
     * that shorter time intervals allow greater precision -- the
     * value means minutes from zero until the MINS_LIMIT (inclusive),
     * upon which it means hours until the HOURS_LIMIT, and so
     * forth. (See 3GPP2 C.S0015-B, v2, 4.5.6-1)
     */
    public static final int RELATIVE_TIME_MINS_LIMIT      = 143;
    public static final int RELATIVE_TIME_HOURS_LIMIT     = 167;
    public static final int RELATIVE_TIME_DAYS_LIMIT      = 196;
    public static final int RELATIVE_TIME_WEEKS_LIMIT     = 244;
    public static final int RELATIVE_TIME_INDEFINITE      = 245;
    public static final int RELATIVE_TIME_NOW             = 246;
    public static final int RELATIVE_TIME_MOBILE_INACTIVE = 247;
    public static final int RELATIVE_TIME_RESERVED        = 248;

    public boolean validityPeriodRelativeSet;
    public int validityPeriodRelative;
    public boolean deferredDeliveryTimeRelativeSet;
    public int deferredDeliveryTimeRelative;

    /**
     * The Reply Option subparameter contains 1-bit values which
     * indicate whether SMS acknowledgment is requested or not.  (See
     * 3GPP2 C.S0015-B, v2, 4.5.11)
     */
    public boolean userAckReq;
    public boolean deliveryAckReq;
    public boolean readAckReq;
    public boolean reportReq;

    /**
     * The Number of Messages subparameter (8-bit value) is a decimal
     * number in the 0 to 99 range representing the number of messages
     * stored at the Voice Mail System. This element is used by the
     * Voice Mail Notification service.  (See 3GPP2 C.S0015-B, v2,
     * 4.5.12)
     */
    public int numberOfMessages;

    /**
     * The Message Deposit Index subparameter is assigned by the
     * message center as a unique index to the contents of the User
     * Data subparameter in each message sent to a particular mobile
     * station. The mobile station, when replying to a previously
     * received short message which included a Message Deposit Index
     * subparameter, may include the Message Deposit Index of the
     * received message to indicate to the message center that the
     * original contents of the message are to be included in the
     * reply.  (See 3GPP2 C.S0015-B, v2, 4.5.18)
     */
    public int depositIndex;

    /**
     * 4-bit or 8-bit value that indicates the number to be dialed in reply to a
     * received SMS message.
     * (See 3GPP2 C.S0015-B, v2, 4.5.15)
     */
    public CdmaSmsAddress callbackNumber;

    /**
     * CMAS warning notification information.
     * @see #decodeCmasUserData(BearerData, int)
     */
    public SmsCbCmasInfo cmasWarningInfo;

    /**
     * The Service Category Program Data subparameter is used to enable and disable
     * SMS broadcast service categories to display. If this subparameter is present,
     * this field will contain a list of one or more
     * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the
     * operation(s) to perform.
     */
    public ArrayList<CdmaSmsCbProgramData> serviceCategoryProgramData;

    /**
     * The Service Category Program Results subparameter informs the message center
     * of the results of a Service Category Program Data request.
     */
    public ArrayList<CdmaSmsCbProgramResults> serviceCategoryProgramResults;


    private static class CodingException extends Exception {
        public CodingException(String s) ;

    }

    /**
     * Returns the language indicator as a two-character ISO 639 string.
     * @return a two character ISO 639 language code
     */
    public String getLanguage() ;


    /**
     * Converts a CDMA language indicator value to an ISO 639 two character language code.
     * @param languageValue the CDMA language value to convert
     * @return the two character ISO 639 language code for the specified value, or null if unknown
     */
    private static String getLanguageCodeForValue(int languageValue) ;


    @Override
    public String toString() ;


    private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static int countAsciiSeptets(CharSequence msg, boolean force) ;


    /**
     * Calculate the message text encoding length, fragmentation, and other details.
     *
     * @param msg message text
     * @param force7BitEncoding ignore (but still count) illegal characters if true
     * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg
     * @return septet count, or -1 on failure
     */
    public static TextEncodingDetails calcTextEncodingDetails(CharSequence msg,
            boolean force7BitEncoding, boolean isEntireMsg) ;


    private static byte[] encode7bitAscii(String msg, boolean force)
        throws CodingException
    ;


    private static byte[] encodeUtf16(String msg)
        throws CodingException
    ;


    private static class Gsm7bitCodingResult {
        int septets;
        byte[] data;
    }

    private static Gsm7bitCodingResult encode7bitGsm(String msg, int septetOffset, boolean force)
        throws CodingException
    ;


    private static void encode7bitEms(UserData uData, byte[] udhData, boolean force)
        throws CodingException
    ;


    private static void encode16bitEms(UserData uData, byte[] udhData)
        throws CodingException
    ;


    private static void encodeEmsUserDataPayload(UserData uData)
        throws CodingException
    ;


    private static byte[] encodeShiftJis(String msg) throws CodingException ;


    private static void encodeUserDataPayload(UserData uData)
        throws CodingException
    ;


    private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException, CodingException
    ;


    private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static byte[] encodeDtmfSmsAddress(String address) ;


    /*
     * TODO(cleanup): CdmaSmsAddress encoding should make use of
     * CdmaSmsAddress.parse provided that DTMF encoding is unified,
     * and the difference in 4-bit vs. 8-bit is resolved.
     */

    private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException ;


    private static void encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException, CodingException
    ;


    private static void encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeValidityPeriodRel(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodePrivacyIndicator(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeLanguageIndicator(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeDisplayMode(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodePriorityIndicator(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    private static void encodeScpResults(BearerData bData, BitwiseOutputStream outStream)
        throws BitwiseOutputStream.AccessException
    ;


    /**
     * Create serialized representation for BearerData object.
     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
     *
     * @param bData an instance of BearerData.
     *
     * @return byte array of raw encoded SMS bearer data.
     */
    public static byte[] encode(BearerData bData) ;


    private static boolean decodeMessageId(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeReserved(
            BearerData bData, BitwiseInputStream inStream, int subparamId)
        throws BitwiseInputStream.AccessException, CodingException
    ;


    private static boolean decodeUserData(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException
    ;


    private static String decodeUtf8(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static String decodeUtf16(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static String decodeCharset(byte[] data, int offset, int numFields, int width,
            String charset) throws CodingException
    ;


    private static String decode7bitAscii(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static String decode7bitGsm(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static String decodeLatin(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static String decodeShiftJis(byte[] data, int offset, int numFields)
        throws CodingException
    ;


    private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
        throws CodingException
    ;


    /**
     * IS-91 Voice Mail message decoding
     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
     * (For character encodings, see TIA/EIA/IS-91, Annex B)
     *
     * Protocol Summary: The user data payload may contain 3-14
     * characters.  The first two characters are parsed as a number
     * and indicate the number of voicemails.  The third character is
     * either a SPACE or '!' to indicate normal or urgent priority,
     * respectively.  Any following characters are treated as normal
     * text user data payload.
     *
     * Note that the characters encoding is 6-bit packed.
     */
    private static void decodeIs91VoicemailStatus(BearerData bData)
        throws BitwiseInputStream.AccessException, CodingException
    ;


    /**
     * IS-91 Short Message decoding
     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
     * (For character encodings, see TIA/EIA/IS-91, Annex B)
     *
     * Protocol Summary: The user data payload may contain 1-14
     * characters, which are treated as normal text user data payload.
     * Note that the characters encoding is 6-bit packed.
     */
    private static void decodeIs91ShortMessage(BearerData bData)
        throws BitwiseInputStream.AccessException, CodingException
    ;


    /**
     * IS-91 CLI message (callback number) decoding
     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
     *
     * Protocol Summary: The data payload may contain 1-32 digits,
     * encoded using standard 4-bit DTMF, which are treated as a
     * callback number.
     */
    private static void decodeIs91Cli(BearerData bData) throws CodingException ;


    private static void decodeIs91(BearerData bData)
        throws BitwiseInputStream.AccessException, CodingException
    ;


    private static boolean decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeDepositIndex(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
        throws CodingException
    ;


    private static void decodeSmsAddress(CdmaSmsAddress addr) throws CodingException ;


    private static boolean decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException, CodingException
    ;


    private static boolean decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeMsgCenterTimeStamp(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeValidityAbs(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeDeferredDeliveryAbs(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeValidityRel(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeDeferredDeliveryRel(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeUserResponseCode(BearerData bData, BitwiseInputStream inStream)
        throws BitwiseInputStream.AccessException ;


    private static boolean decodeServiceCategoryProgramData(BearerData bData,
            BitwiseInputStream inStream) throws BitwiseInputStream.AccessException, CodingException
    ;


    private static int serviceCategoryToCmasMessageClass(int serviceCategory) ;


    /**
     * Calculates the number of bits to read for the specified number of encoded characters.
     * @param msgEncoding the message encoding to use
     * @param numFields the number of characters to read. For Shift-JIS and Korean encodings,
     *  this is the number of bytes to read.
     * @return the number of bits to read from the stream
     * @throws CodingException if the specified encoding is not supported
     */
    private static int getBitsForNumFields(int msgEncoding, int numFields)
            throws CodingException ;


    /**
     * CMAS message decoding.
     * (See TIA-1149-0-1, CMAS over CDMA)
     *
     * @param serviceCategory is the service category from the SMS envelope
     */
    private static void decodeCmasUserData(BearerData bData, int serviceCategory)
            throws BitwiseInputStream.AccessException, CodingException ;


    /**
     * Create BearerData object from serialized representation.
     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
     *
     * @param smsData byte array of raw encoded SMS bearer data.
     * @return an instance of BearerData.
     */
    public static BearerData decode(byte[] smsData) ;


    private static boolean isCmasAlertCategory(int category) ;


    /**
     * Create BearerData object from serialized representation.
     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
     *
     * @param smsData byte array of raw encoded SMS bearer data.
     * @param serviceCategory the envelope service category (for CMAS alert handling)
     * @return an instance of BearerData.
     */
    public static BearerData decode(byte[] smsData, int serviceCategory) ;


    // MTK-START
    /**
     * Support encode Ems with the octet encoding.
     * @param uData The user data.
     * @param udhData The user data header.
     */
    private static void encodeOctetEms(UserData uData, byte[] udhData) ;


    /**
     * Support encode Ems with the 7bitAscii encoding type.
     * @param uData The user data.
     * @param udhData The user data header.
     * @param force If force to use 7bit encode.
     * @throws CodingException
     */
    private static void encode7bitAsciiEms(UserData uData, byte[] udhData, boolean force)
            throws CodingException
    ;


    /**
     * Calculate the message text encoding length, fragmentation, and other details.
     *
     * @param msg message text
     * @param force7BitEncoding ignore (but still count) illegal characters if true
     * @param encodingType the encoding type of content of message(GSM 7-bit, Unicode or Automatic)
     * @return septet count, or -1 on failure
     */
    public static TextEncodingDetails calcTextEncodingDetails(CharSequence msg,
            boolean force7BitEncoding, int encodingType) ;


    /**
     * Convert the int to the BCD byte.
     * @param value The int need to be converted.
     * @return the BCD byte for value.
     */
    private static byte cdmaIntToBcdByte(int value) ;


    /**
     * Encode the message centre time into the BearerData.
     * @param bData The bearer data.
     * @param outStream the output stream for PDU.
     * @throws BitwiseOutputStream.AccessException
     */
    private static void encodeMsgCenterTimeStamp(BearerData bData, BitwiseOutputStream outStream)
            throws BitwiseOutputStream.AccessException ;

    // MTK-END
}
